#include <algorithm>
#include <mutex>

#include "common/elements/element.h"
#include "common/more/string.h"

#include "phase.h"

namespace Elements
{

Phase::Phase(const Phase& other)
    : Element(other)
    , m_projectId(other.m_projectId)
    , m_caption(other.m_caption)
    , m_description(other.m_description)
    , m_searchCaption(other.m_searchCaption)
    , m_searchDescription(other.m_searchDescription)
    , m_beginDate(other.m_beginDate)
    , m_endDate(other.m_endDate)
{
}

bool Phase::isSame(Element* const other) const
{
    const auto otherElement = dynamic_cast<Phase const*>(other);
    if (nullptr == otherElement)
        return false;

    return bool(
        m_id == otherElement->m_id
        && m_projectId == otherElement->m_projectId
        && m_caption == otherElement->m_caption
        && m_description == otherElement->m_description
        && m_searchCaption == otherElement->m_searchCaption
        && m_searchDescription == otherElement->m_searchDescription
        && m_beginDate == otherElement->m_beginDate
        && m_endDate == otherElement->m_endDate
    );
}

Common::Json Phase::toJson() const
{
    std::shared_lock locker(m_lock);
    Common::Json result;
    result["id"] = m_id;
    result["elementType"] = unsigned(elementType());
    result["projectId"] = m_projectId;
    result["caption"] = m_caption;
    result["description"] = m_description;
    result["searchCaption"] = m_searchCaption;
    result["searchDescription"] = m_searchDescription;
    result["beginDate"] = m_beginDate;
    result["endDate"] = m_endDate;
    return result;
}

void Phase::fromJson(const Common::Json& json)
{
    std::shared_lock locker(m_lock);
    m_id = json["id"].get<unsigned>();
    m_projectId = json["projectId"].get<unsigned>();
    m_caption = json["caption"].get<std::string>();
    m_description = json["description"].get<std::string>();
    m_searchCaption = json["searchCaption"].get<std::string>();
    m_searchDescription = json["searchDescription"].get<std::string>();
    m_beginDate = json["beginDate"].get<std::time_t>();
    m_endDate = json["endDate"].get<std::time_t>();
}

Element* Phase::clone() const
{
    return new Phase(*this);
}

ElementType Phase::elementType() const
{
    return ElementType::Phase;
}

unsigned Phase::projectId() const
{
    std::shared_lock locker(m_lock);
    return m_projectId;
}

void Phase::setProjectId(unsigned value)
{
    std::unique_lock locker(m_lock);
    m_projectId = value;
}

std::string Phase::caption() const
{
    std::shared_lock locker(m_lock);
    return m_caption;
}

void Phase::setCaption(const std::string& value)
{
    std::unique_lock locker(m_lock);
    m_caption = value;
    locker.unlock();
    setSearchCaption(value);
}

std::string Phase::description() const
{
    std::shared_lock locker(m_lock);
    return m_description;
}

void Phase::setDescription(const std::string& value)
{
    std::unique_lock locker(m_lock);
    m_description = value;
    locker.unlock();
    setSearchDescription(value);
}

std::string Phase::searchCaption() const
{
    std::shared_lock locker(m_lock);
    return m_searchCaption;
}

void Phase::setSearchCaption(const std::string& value)
{
    std::unique_lock locker(m_lock);
    m_searchCaption = Common::toLowerCase(value);
}

std::string Phase::searchDescription() const
{
    std::shared_lock locker(m_lock);
    return m_searchDescription;
}

void Phase::setSearchDescription(const std::string& value)
{
    std::unique_lock locker(m_lock);
    m_searchDescription = Common::toLowerCase(value);
}

std::time_t Phase::beginDate() const
{
    std::shared_lock locker(m_lock);
    return m_beginDate;
}

void Phase::setBeginDate(const std::time_t& value)
{
    std::unique_lock locker(m_lock);
    m_beginDate = value;
}

std::time_t Phase::endDate() const
{
    std::shared_lock locker(m_lock);
    return m_endDate;
}

void Phase::setEndDate(const std::time_t& value)
{
    std::unique_lock locker(m_lock);
    m_endDate = value;
}

} // namespace Elements
